﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using LM.YF.K3Cloud.Plugin.Models;
using LM.YF.K3Cloud.Plugin.Models.Grasses;
using LM.YF.K3Cloud.Plugin.Models.VOs;
using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace LM.YF.K3Cloud.Plugin
{
    /// <summary>
    /// 鹿奔
    /// </summary>
    [HotUpdate, Description("操作后计算结算单价（挂载到销售订单新变更单）")]
    public class CalcSettlementPriceOperationServicePlugin4 : AbstractOperationServicePlugIn
    {
        #region MyRegion

        /// <summary>
        /// 源单编号
        /// </summary>
        private readonly ElementKeySchema FSrcBillNo = new ElementKeySchema
        {
            FormKey = "FSrcBillNo",
            DbKey = "FSRCBILLNO",
            OrmKey = "SrcBillNo"
        };

        /// <summary>
        /// 源单序号
        /// </summary>
        private readonly ElementKeySchema FOBillSeq = new ElementKeySchema
        {
            FormKey = "FOBillSeq",
            DbKey = "FOBILLSEQ",
            OrmKey = "OBillSeq"
        };

        private readonly ElementKeySchema FSaleOrderEntry = new ElementKeySchema
        {
            FormKey = "FSaleOrderEntry",
            DbKey = "T_SAL_XORDERENTRY",
            OrmKey = "SaleOrderEntry"
        };

        /// <summary>
        /// 税率
        /// </summary>
        private readonly ElementKeySchema FEntryTaxRate = new ElementKeySchema
        {
            FormKey = "FEntryTaxRate",
            DbKey = "FTAXRATE",
            OrmKey = "TaxRate"
        };

        #endregion

        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            base.OnPreparePropertys(e);
        }

        public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e)
        {
            base.AfterExecuteOperationTransaction(e);

            var failureList = new List<string>();
            foreach (var row in e.SelectedRows)
            {
                var failure = AfterExecuteOperationTransaction(row);
                if (failure != null)
                {
                    failureList.Add(failure);
                }
            }
            if (failureList.Count > 0)
            {
                throw new KDBusinessException(null, string.Join("\r\n", failureList));
            }
        }

        private string AfterExecuteOperationTransaction(ExtendedDataEntity orderBill)
        {
            var billEntity = orderBill.DataEntity;

            var orderId = Convert.ToInt32(billEntity["PKIDX"]);
            var orderDataCollection = DBUtils.ExecuteDynamicObject(Context, $@"select a.FID, a.FSALEORGID
                    , b.FNAME, a.FBILLNO
                from T_SAL_ORDER as a
                inner join T_ORG_ORGANIZATIONS_L as b on b.FLOCALEID = 2052 and b.FORGID = a.FSALEORGID
                where a.FID = '{orderId}';");
            if (!(orderDataCollection?.Count > 0))
            {
                return $"销售订单（ID：{orderId}）不存在！";
            }
            var orderData = orderDataCollection[0];
            var orderNo = Convert.ToString(orderData["FBILLNO"]);
            var saleOrgName = Convert.ToString(orderData["FNAME"]);
            //if (!new string[] { "利民控股集团股份有限公司", "河北威远生物化工有限公司" }.Contains(saleOrgName))
            //{
            //    return null;
            //}

            var saleOrgId = Convert.ToInt32(orderData["FSALEORGID"]);
            var entryCollection = billEntity[FSaleOrderEntry.OrmKey] as DynamicObjectCollection;
            foreach (var entryData in entryCollection)
            {
                var orderEntryId = Convert.ToInt32(entryData["PKIDX"]);
                var failure = CalcDeliveryNotice(saleOrgId, saleOrgName, orderEntryId);
                if (failure != null)
                {
                    return $"重算销售订单（{orderNo}）下游单据的结算单价失败：{failure}";
                }
            }

            return null;
        }

        private string CalcDeliveryNotice(int saleOrgId, string saleOrgName, int salesOrderEntryId)
        {
            var noticeDataCollection = DBUtils.ExecuteDynamicObject(Context, $@"select a.FID, a.F_RDLV_SALER2
                    , a.FDELIVERYORGID, b.FNAME, c.FSETTLECURRID, c.FEXCHANGERATE, a.FBILLNO
                from T_SAL_DELIVERYNOTICE as a
                inner join T_ORG_ORGANIZATIONS_L as b on b.FLOCALEID = 2052 and b.FORGID = a.FDELIVERYORGID
                inner join T_SAL_DELIVERYNOTICEFIN as c on c.FID = a.FID
                where a.FID in (
	                select b.FID
	                from T_SAL_DELIVERYNOTICEENTRY_LK as a
	                inner join T_SAL_DELIVERYNOTICEENTRY as b on b.FENTRYID = a.FENTRYID
	                where a.FSTABLENAME = 'T_SAL_ORDERENTRY' and a.FSID = {salesOrderEntryId}
                );");
            if (!(noticeDataCollection?.Count > 0))
            {
                return null;
            }

            foreach (var noticeData in noticeDataCollection)
            {
                var stockOrgName = Convert.ToString(noticeData["FNAME"]);
                if (saleOrgName.Equals(stockOrgName))
                {
                    continue;
                }

                var stockOrgId = Convert.ToInt32(noticeData["FDELIVERYORGID"]);
                var salerId = Convert.ToInt32(noticeData["F_RDLV_SALER2"]);
                if (stockOrgId == 0 || salerId == 0)
                {
                    continue;
                }

                var exchangeRate = 1M;// 汇率
                var settleCurr = Convert.ToInt32(noticeData["FSETTLECURRID"]);
                var isCny = settleCurr == 1;// 是否为人民币
                if (!isCny)
                {
                    exchangeRate = Convert.ToDecimal(noticeData["FEXCHANGERATE"]);
                }

                var noticeId = Convert.ToInt32(noticeData["FID"]);
                var entries = DBUtils.ExecuteDynamicObject(Context, $@"select a.FENTRYID, b.FTAXPRICE
                        , a.FMATERIALID, a.F_QLTK_SEAAIRFREIGHT, a.F_QLTK_PREMIUM, a.F_QLTK_COMMISSION
                        , a.F_QLTK_OTHER1, b.FPRICEUNITQTY, a.FSEQ
                    from T_SAL_DELIVERYNOTICEENTRY as a
                    inner join T_SAL_DELIVERYNOTICEENTRY_F as b on b.FENTRYID = a.FENTRYID
                    where a.FID = {noticeId};");

                var vo = new avnn1
                {
                    SaleOrgId = saleOrgId,
                    ExchangeRate = exchangeRate,
                    EntryDataCount = entries.Count,
                    SalerId = salerId,
                    StockOrgId = stockOrgId
                };
                var vo2 = new vna1
                {
                    GetInputs = entryIndex =>
                    {
                        var entry = entries[entryIndex];
                        return new smznb111
                        {
                            Commission = Convert.ToDecimal(entry["F_QLTK_COMMISSION"]),
                            OtherFee = Convert.ToDecimal(entry["F_QLTK_OTHER1"]),
                            Premium = Convert.ToDecimal(entry["F_QLTK_PREMIUM"]),
                            PriceQty = Convert.ToDecimal(entry["FPRICEUNITQTY"]),
                            SaFreight = Convert.ToDecimal(entry["F_QLTK_SEAAIRFREIGHT"]),
                            TaxPrice = Convert.ToDecimal(entry["FTAXPRICE"]),
                            MaterialId = Convert.ToInt32(entry["FMATERIALID"]),
                            TaxRate = Convert.ToDecimal(entry[FEntryTaxRate.OrmKey])
                        };
                    },
                    OnCalculated = (settlementPrice, coefficient, entryIndex) =>
                    {
                        var entry = entries[entryIndex];
                        var entryId = Convert.ToInt32(entry["FENTRYID"]);
                        DBUtils.Execute(Context, $@"update T_SAL_DELIVERYNOTICEENTRY
                            set F_RDLV_COEFFICIENT = {coefficient}, F_RDLV_SETTLEMENT_PRICE = {settlementPrice}
                            where FENTRYID = {entryId};");
                    }
                };
                var failure = CalcSettlementPriceOperationServicePlugin.CalcSettlementPrice(Context, vo, vo2);

                if (!failure.Successful)
                {
                    var noticeBillNo = Convert.ToString(noticeData["FBILLNO"]);
                    return $"发货通知单（{noticeBillNo}）计算结算单价失败：{failure.Message}";
                }

                failure = CalcOutStock(saleOrgId, saleOrgName, noticeId);
                if (!failure.Successful)
                {
                    return failure.Message;
                }
            }

            return null;
        }

        private Result CalcOutStock(int saleOrgId, string saleOrgName, int noticeId)
        {
            var outstockDataCollection = DBUtils.ExecuteDynamicObject(Context, $@"select a.FID, a.F_RDLV_SALER2
                    , a.FSTOCKORGID, b.FNAME, c.FSETTLECURRID, c.FEXCHANGERATE, a.FBILLNO
                from T_SAL_OUTSTOCK as a
                inner join T_ORG_ORGANIZATIONS_L as b on b.FLOCALEID = 2052 and b.FORGID = a.FSTOCKORGID
                inner join T_SAL_OUTSTOCKFIN as c on c.FID = a.FID
                where a.FID in (
                    select b.FID
                    from T_SAL_OUTSTOCKENTRY_LK as a
                    inner join T_SAL_OUTSTOCKENTRY as b on b.FENTRYID = a.FENTRYID
                    where a.FSTABLENAME = 'T_SAL_DELIVERYNOTICEENTRY' and a.FSBILLID = {noticeId}
                );");
            if (!(outstockDataCollection?.Count > 0))
            {
                return new Result
                {
                    Successful = true
                };
            }

            foreach (var outstockData in outstockDataCollection)
            {
                var stockOrgName = Convert.ToString(outstockData["FNAME"]);
                if (saleOrgName.Equals(stockOrgName))
                {
                    continue;
                }

                var stockOrgId = Convert.ToInt32(outstockData["FSTOCKORGID"]);
                var salerId = Convert.ToInt32(outstockData["F_RDLV_SALER2"]);
                if (stockOrgId == 0 || salerId == 0)
                {
                    continue;
                }

                var exchangeRate = 1M;// 汇率
                var settleCurr = Convert.ToInt32(outstockData["FSETTLECURRID"]);
                var isCny = settleCurr == 1;// 是否为人民币
                if (!isCny)
                {
                    exchangeRate = Convert.ToDecimal(outstockData["FEXCHANGERATE"]);
                }

                var outstokcId = Convert.ToInt32(outstockData["FID"]);
                var entries = DBUtils.ExecuteDynamicObject(Context, $@"select a.FENTRYID, b.FTAXPRICE
	                    , a.FMATERIALID, a.F_QLTK_SEAAIRFREIGHT, a.F_QLTK_PREMIUM, a.F_QLTK_COMMISSION
	                    , a.F_QLTK_OTHER1, b.FPRICEUNITQTY, a.FSEQ
                    from T_SAL_OUTSTOCKENTRY as a
                    inner join T_SAL_OUTSTOCKENTRY_F as b on b.FENTRYID = a.FENTRYID
                    where a.FID = {outstokcId};");

                var vo = new avnn1
                {
                    StockOrgId = saleOrgId,
                    SalerId = salerId,
                    EntryDataCount = entries.Count,
                    ExchangeRate = exchangeRate,
                    SaleOrgId = saleOrgId
                };
                var vo2 = new vna1
                {
                    GetInputs = entryIndex =>
                    {
                        var entry = entries[entryIndex];
                        return new smznb111
                        {
                            Commission = Convert.ToDecimal(entry["F_QLTK_COMMISSION"]),
                            OtherFee = Convert.ToDecimal(entry["F_QLTK_OTHER1"]),
                            Premium = Convert.ToDecimal(entry["F_QLTK_PREMIUM"]),
                            PriceQty = Convert.ToDecimal(entry["FPRICEUNITQTY"]),
                            SaFreight = Convert.ToDecimal(entry["F_QLTK_SEAAIRFREIGHT"]),
                            TaxPrice = Convert.ToDecimal(entry["FTAXPRICE"]),
                            MaterialId = Convert.ToInt32(entry["FMATERIALID"]),
                            TaxRate = Convert.ToDecimal(entry[FEntryTaxRate.OrmKey])
                        };
                    },
                    OnCalculated = (settlementPrice, coefficient, entryIndex) =>
                    {
                        var entry = entries[entryIndex];
                        var entryId = Convert.ToInt32(entry["FENTRYID"]);
                        DBUtils.Execute(Context, $@"update T_SAL_OUTSTOCKENTRY
                            set F_RDLV_COEFFICIENT = {coefficient}, F_RDLV_SETTLEMENT_PRICE = {settlementPrice}
                            where FENTRYID = {entryId};");
                    }
                };
                var failure = CalcSettlementPriceOperationServicePlugin.CalcSettlementPrice(Context, vo, vo2);

                if (!failure.Successful)
                {
                    var outstockBillNo = Convert.ToString(outstockData["FBILLNO"]);
                    return new Result
                    {
                        Successful = false,
                        Message = $"销售出库单（{outstockBillNo}）计算结算单价失败：{failure.Message}"
                    };
                }
            }

            return new Result
            {
                Successful = true
            };
        }
    }
}
